package file_watcher

import (
	"errors"
	"golang.org/x/sys/unix"
	"strconv"
)

type epller struct {

	fds map[string]int

	epllerFd int
}

func Newepller()(*epller,error){
	epFd,errno := unix.EpollCreate(1)
	if errno != nil{
		return nil,errno
	}

	return &epller{make(map[string]int),epFd},nil
}

func (ep *epller)AddFd(name string,fd int)(err error)  {

	var errno error

	ep.fds[name] = fd

	event := unix.EpollEvent{
		Fd:     int32(ep.fds[name]),
		Events: unix.EPOLLIN | unix.EPOLLERR,
	}

	errno = unix.EpollCtl(ep.epllerFd, unix.EPOLL_CTL_ADD, ep.fds[name], &event)
	if errno != nil {
		return errno
	}

	return nil
}

func (ep *epller)EpWait()(error)  {

	var events  = make([]unix.EpollEvent,4 * len(ep.fds))
	for {
		n, err := unix.EpollWait(ep.epllerFd, events, -1)
		if n == -1 {
			if err == unix.EINTR {
				continue
			}
			return err
		}

		if err != nil{
			return err
		}
		if n == 0 {
			continue
		}
		readEv := events[:n]
		for _,event := range readEv{
			if event.Events&unix.EPOLLERR != 0{
               return errors.New(strconv.Itoa(int(event.Fd)) + "has error")
			}
		}
		return nil
	}
}

func (ep *epller)CloseFd()  {

	if ep.epllerFd != -1{
	   unix.Close(ep.epllerFd)
	   ep.epllerFd = 0
	}
}